//
//  GSModel.cpp
//  GSEngine
//
//  Created by Александр on 02.02.14.
//  Copyright (c) 2014 SNK. All rights reserved.
//

#include "GSModel.h"

namespace GSEngine
{
    GSModel::GSModel()
    {
    }
    GSModel::~GSModel()
    {
    }
    void GSModel::loadModel(const char* path, const char* permission)
    {
        int i;
        unsigned short l_chunk_id;
        unsigned int l_chunk_length;
        unsigned char l_char;
        unsigned short l_qty;
        unsigned short l_face_flags;
        
        m_file=fopen(path, permission);
        if (m_file != NULL)
        {
            fseek(m_file, 0L, SEEK_END);
            long sz = ftell(m_file);
            fseek(m_file, 0L, SEEK_SET);
            while (ftell (m_file) < sz) //Loop to scan the whole file
            {
                
                fread (&l_chunk_id, 2, 1, m_file);
                
                fread (&l_chunk_length, 4, 1, m_file);
                
                
                switch (l_chunk_id)
                {
                        //----------------- MAIN3DS Сцена 3DS-----------------
                        
                    case 0x4d4d:
                        break;
                        
                        //----------------- EDIT3DS Всяческие обьекты-----------------
                        
                    case 0x3d3d:
                        break;
                        
                        //--------------- EDIT_OBJECT объект---------------
                        
                    case 0x4000:
                        i=0;
                        do
                        {
                            fread (&l_char, 1, 1, m_file);
                            m_object.name[i]=l_char;
                            i++;
                        }while(l_char != '\0' && i<20);
                        break;
                        
                        //--------------- OBJ_TRIMESH trimesh-объект---------------
                    case 0x4100:
                        break;
                        
                        //--------------- TRI_VERTEXL список вершин---------------
                        
                    case 0x4110:
                        fread (&l_qty, sizeof (unsigned short), 1, m_file);
                        m_object.vertices_qty = l_qty;
                        
                        for (i=0; i<l_qty; i++)
                        {
                            fread (&m_object.vertex[i].x, sizeof(float), 1, m_file);
                            
                            fread (&m_object.vertex[i].y, sizeof(float), 1, m_file);
                            
                            fread (&m_object.vertex[i].z, sizeof(float), 1, m_file);
                            
                        }
                        break;
                        
                        //--------------- TRI_FACEL1 список граней----------------
                        
                    case 0x4120:
                        fread (&l_qty, sizeof (unsigned short), 1, m_file);
                        m_object.polygons_qty = l_qty;
                        
                        for (i=0; i<l_qty; i++)
                        {
                            fread (&m_object.indices[i].a, sizeof (unsigned short), 1, m_file);
                            
                            fread (&m_object.indices[i].b, sizeof (unsigned short), 1, m_file);
                            
                            fread (&m_object.indices[i].c, sizeof (unsigned short), 1, m_file);
                            
                            fread (&l_face_flags, sizeof (unsigned short), 1, m_file);
                            
                        }
                        break;
                        
                        //------------- TRI_MAPPINGCOORS текстурные координаты------------
                        
                    case 0x4140:
                        fread (&l_qty, sizeof (unsigned short), 1, m_file);
                        for (i=0; i<(l_qty); i++)
                        {
                            fread (&m_object.mapcoord[i].u, sizeof (float), 1, m_file);
                            fread (&m_object.mapcoord[i].v, sizeof (float), 1, m_file);
                            
                        }
                        break;
                        
                    default:
                        fseek(m_file, l_chunk_length-6, SEEK_CUR);
                }
            }
            for (int i = 0; i < m_object.polygons_qty; i++)
            {
                normal_type temp = getNormal(m_object.vertex[m_object.indices[i].a],
                                             m_object.vertex[m_object.indices[i].b],
                                             m_object.vertex[m_object.indices[i].c]);
                m_object.normals[i*3 + 0] = temp;
                m_object.normals[i*3 + 1] = temp;
                m_object.normals[i*3 + 2] = temp;
            }
            fclose (m_file); // Closes the file stream
        }
    }
    
/*
    
    void ris3DS()
    {
        int l_index;
        glBegin(GL_TRIANGLES);
        for (l_index=0;l_index<object_3d.polygons_qty;l_index++)
        {
            //----------------- ПЕРВАЯ ВЕРШИНА -----------------
            vertex_type p1 = object_3d.vertex[ object_3d.polygon[l_index].a ];
            vertex_type p2 = object_3d.vertex[ object_3d.polygon[l_index].b ];
            vertex_type p3 = object_3d.vertex[ object_3d.polygon[l_index].c ];
            normal_type norm = getNormal(p1, p2, p3);
            glNormal3f(norm.x, norm.y, norm.z);
            // Координаты Текстуры первой вершины
            glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].a ].u,
                         object_3d.mapcoord[ object_3d.polygon[l_index].a ].v);
            // Координаты первой вершины
            glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].a ].x,
                       object_3d.vertex[ object_3d.polygon[l_index].a ].y,
                       object_3d.vertex[ object_3d.polygon[l_index].a ].z); //Vertex definition
            
            //----------------- ВТОРАЯ ВЕРШИНА -----------------
            
            // Координаты Текстуры второй вершины
            glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].b ].u,
                         object_3d.mapcoord[ object_3d.polygon[l_index].b ].v);
            
            // Координаты второй вершины
            glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].b ].x,
                       object_3d.vertex[ object_3d.polygon[l_index].b ].y,
                       object_3d.vertex[ object_3d.polygon[l_index].b ].z);
            
            //----------------- ТРЕТЬЯ ВЕРШИНА -----------------
            
            // Координаты Текстуры третьей вершины
            glTexCoord2f( object_3d.mapcoord[ object_3d.polygon[l_index].c ].u,
                         object_3d.mapcoord[ object_3d.polygon[l_index].c ].v);
            
            // Координаты Третьей вершины
            glVertex3f( object_3d.vertex[ object_3d.polygon[l_index].c ].x,
                       object_3d.vertex[ object_3d.polygon[l_index].c ].y,
                       object_3d.vertex[ object_3d.polygon[l_index].c ].z);
        }
        glEnd();
    }
 
 
 float gCubeVertexData[108] =
 {
 // Data layout for each line below is:
 // positionX, positionY, positionZ,
 0.5f, -0.5f, -0.5f,
 0.5f, 0.5f, -0.5f,
 0.5f, -0.5f, 0.5f,
 0.5f, -0.5f, 0.5f,
 0.5f, 0.5f, -0.5f,
 0.5f, 0.5f, 0.5f,
 
 0.5f, 0.5f, -0.5f,
 -0.5f, 0.5f, -0.5f,
 0.5f, 0.5f, 0.5f,
 0.5f, 0.5f, 0.5f,
 -0.5f, 0.5f, -0.5f,
 -0.5f, 0.5f, 0.5f,
 
 -0.5f, 0.5f, -0.5f,
 -0.5f, -0.5f, -0.5f,
 -0.5f, 0.5f, 0.5f,
 -0.5f, 0.5f, 0.5f,
 -0.5f, -0.5f, -0.5f,
 -0.5f, -0.5f, 0.5f,
 
 -0.5f, -0.5f, -0.5f,
 0.5f, -0.5f, -0.5f,
 -0.5f, -0.5f, 0.5f,
 -0.5f, -0.5f, 0.5f,
 0.5f, -0.5f, -0.5f,
 0.5f, -0.5f, 0.5f,
 
 0.5f, 0.5f, 0.5f,
 -0.5f, 0.5f, 0.5f,
 0.5f, -0.5f, 0.5f,
 0.5f, -0.5f, 0.5f,
 -0.5f, 0.5f, 0.5f,
 -0.5f, -0.5f, 0.5f,
 
 0.5f, -0.5f, -0.5f,
 -0.5f, -0.5f, -0.5f,
 0.5f, 0.5f, -0.5f,
 0.5f, 0.5f, -0.5f,
 -0.5f, -0.5f, -0.5f,
 -0.5f, 0.5f, -0.5f,
 };

*/
    normal_type GSModel::getNormal(vertex_type p1, vertex_type p2, vertex_type p3)
    {
        normal_type n;
        float x1=p1.x, x2=p2.x, x3=p3.x;
        float y1=p1.y, y2=p2.y, y3=p3.y;
        float z1=p1.z, z2=p2.z, z3=p3.z;
        n.x = (y2-y1)*(z3-z1)-(y3-y1)*(z2-z1);
        n.y = (x2-x1)*(z3-z1)-(x3-x1)*(z2-z1);
        n.z = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1);
        return n;
    }
    int GSModel::getVertexCount()
    {
        return m_object.vertices_qty;
    }
    int GSModel::getIndicesCount()
    {
        return m_object.polygons_qty * 3;
    }
    float* GSModel::getVertexCoordsArray()
    {
        return (float*)&m_object.vertex;
    }
    float* GSModel::getTextureCoordsArray()
    {
        return (float*)&m_object.mapcoord;
    }
    unsigned short* GSModel::getIndicesArray()
    {
        return (unsigned short*)&m_object.indices;
    }
    float* GSModel::getNormalsArray()
    {
        return (float*)&m_object.normals;
    }
}
